asynx.namespace("dom");

asynx.dom = {
	
	ELEMENT_NODE: 1,
	ATTRIBUTE_NODE: 2,
	TEXT_NODE: 3,
	CDATA_SECTION_NODE: 4,
	ENTITY_REFERENCE_NODE: 5,
	ENTITY_NODE: 6,
	PROCESSING_INSTRUCTION_NODE: 7,
	COMMENT_NODE: 8,
	DOCUMENT_NODE: 9,
	DOCUMENT_TYPE_NODE: 10,
	DOCUMENT_FRAGMENT_NODE: 11,
	NOTATION_NODE: 12,
	
	isTextNode: function(node) {
		if (asynx.isObject(node))
			return node.nodeType === this.TEXT_NODE;
	},
	
	isElementNode: function(node) {
		if (asynx.isObject(node))
			return node.nodeType === this.ELEMENT_NODE;
	},
	
	isAttrNode: function(node) {
		if (asynx.isObject(node))
			return node.nodeType === this.ATTRIBUTE_NODE;
	},
	
	isDocNode: function(node) {
		if (asynx.isObject(node))
			return node.nodeType === this.DOCUMENT_NODE;
	},
	
	isDocTypeNode: function(node) {
		if (asynx.isObject(node))
			return node.nodeType === this.DOCUMENT_TYPE_NODE;
	},
	
	walk: function(node, func) {
        func(node);
        node = node.firstChild; 
        while (node) { 
            this.walk(node, func); 
            node = node.nextSibling; 
        } 
    },
	
	walkParents: function(node, func) {
        while (node) { 
	        func(node);
            node = node.parentNode; 
        } 
    },
	
	hasAttribute: function(element, attribute) { 
		element = asynx(element);
		var attributeNode = element.attributes[attribute]; 
		if (attributeNode) 
			if (attributeNode.specified) 
				return true; 
			return false; 
	},
 		 
	getAttribute: function(el, name) {
		el = el.constructor==String?asynx(el):el;
		attr = el.attributes[name];
		return attr?attr.value:null;
	}, 
 		 
	setAttribute: function(element, attribute, value) { 
		return asynx(element).setAttribute(attribute, value); 
	},
	
	getChildNodes: function(rNode) {
		var element = typeof rNode == "object" ? rNode : document.getElementById(rNode);
		var results = []; 
		this.walk(element, function (node) { 
			results.push(node);
	    }); 
	    return results; 
	},
	
	getByClassName: function(className) { 
	    var results = []; 
		var context = arguments[1];
	    this.walk(context?context:document.body, function (node) { 
	        var a, c = node.className, i; 
	        if (c) { 
	            a = c.split(' '); 
	            for (i = 0; i < a.length; i += 1) { 
	                if (a[i] === className) { 
	                    results.push(node); 
	                    break; 
	                } 
	            } 
	        } 
	    }); 
	    return results; 
	},

	getByAttribute: function(attribute) { 
		var sValue = arguments[1];
		
		if (!attribute) return [];
		var xQuery = "[@a='v']".replace("a", attribute);
		
		if (sValue) 
			xQuery=xQuery.replace("v", sValue);
		else
			xQuery=xQuery.replace("='v'", "");
		
		return asynx.xpath.getNodes(xQuery);
	},
	
	getByTagName: function(scopes, sTagName) {
		var nodeStore = [];
		for (var i=0; i<scopes.length;i++) {
			var scope = scopes[i];
			if (!scope) continue;
			var nodes = scope.getElementsByTagName(sTagName);
			asynx.merge(nodeStore, nodes);
		}
		return nodeStore;
	},
	
	getFormByName: function(rForm, sName) {
		var elements = rForm.elements;
		for (var i = 0; i < elements.length; i++) {
			var element = elements[i];
			if (element.name == sName) return element;
		}
		return null;
	},
	
	parseXml: function(xml) {
		var dom = null, PARSE_ERROR = "XML_PARSE_ERROR";
		
		if (window.DOMParser) {
			try { 
				dom = (new DOMParser()).parseFromString(xml, "text/xml"); 
			} 
			catch (e) { dom = null; }
		}
		else if (window.ActiveXObject) {
			try {
				dom = new ActiveXObject('Microsoft.XMLDOM');
				dom.async = false;
				if (!dom.loadXML(xml)) // parse error ..
					return (dom.parseError.reason + dom.parseError.srcText);
			} 
			catch (e) { dom = null; }
		}
		else {
			return PARSE_ERROR;
		}
		return dom;
	},
	
	append: function(f, c) {
		f.appendChild(c);
	},
	
	prepend: function(f, c) {
		f.insertBefore(c, f.firstChild);
	},
	
	before: function(f, c) {
		f.parentNode.insertBefore(c, f);
	},
	
	after: function(f, c) {
		f.parentNode.insertBefore(c, f.nextSibling);
	},
	
	remove: function(f, c) {
		if (c && c.zIndexFixer)
			f.removeChild(asynx(c.zIndexFixer));
		
		f.removeChild(c);
	}
	
};
